//==============================================================================
//
//      DMD5 - the RSA's MD5 message digist algoritme class in the ofc-library
//
//               Copyright (C) 2002  Dick van Oudheusden
//  
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this library; if not, write to the Free
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//==============================================================================
// 
//  $Date: 2005-02-05 06:25:38 $ $Revision: 1.12 $

//==============================================================================

#include "ofc/DMD5.h"

#if _INTERFACE_

#include "ofc/DText.h"
#include "ofc/DData.h"

#include "ofc/md5.h"

// The DMD5 class implements a number of methods for using the RSA's MD5 message
// algorithmes.

@interface DMD5 : Object
{
@private
  MD5_CTX        _md5;      // the md5 context
}

#endif



@implementation DMD5


//// Constructors

//
// Initialise to an empty object
//
// @return the instance
//

- (DMD5 *) init
{
  [super init];

  MD5Init(&_md5);  
  
  return self;
}

//
// Initialise the object with a c-string
//
// @param cstring  the string
//
// @return the object
//

- (DMD5 *) init :(const char *) cstring
{
  [self init];

  [self update :cstring];
  
  return self;
}

//
// Initialise the object with data
//
// @param data     the data ('\0' allowed)
// @param length   the length of the data
//
// @return the object
//

- (DMD5 *) init :(const char *) data :(unsigned long) length
{
  [self init];

  [self update :data :length];

  return self;
}


//// Copy related methods

//
// Deepen the copied object (not implemented)
//
//

- deepen
{
  WARNING(DW_METHOD_NOT_IMPL, "deepen");

  return self;
}


//// Update methods

//
// Update the object with a c-string. Repeated calls can be compared
// to a single call in which the strings are concatted
//
// @param cstring  the c-string to be feeded to md5
//
// @return the object
//

- (DMD5 *) update :(const char *) cstring
{
  int length = (cstring != NULL) ? strlen(cstring) : 0;
  
  if (length > 0)
  {
    MD5Update(&_md5, (unsigned char *) cstring, length);
  }

  return self;
}

//
// Update the object with data. Repeated calls can be compared
// to a single call in which the strings are concatted
//
// @param data     the data to be feeded to md5
// @param length   the length of the data
//
// @return the object
//

- (DMD5 *) update :(const unsigned char *) data :(unsigned long) length
{
  if (length > 0)
  {
    MD5Update(&_md5, (unsigned char *) data, length);
  }

  return self;
}


//// Digest methods

//
// Returns the (current) digest of all data passed to the object. 
//
// @return the (new) data string object with the digest
//

- (DData *) digest
{
  DData         *data = [DData alloc];
  
  MD5_CTX        copy;
  unsigned char  digest[16];

  copy = _md5;
  
  MD5Final(digest, &copy);

  return [data init :digest :16];
}

//
// Return the (current) digest of all data passed to the object. The
// returning string contains the digest in hexadecimal ascii characters.
//
// @return the (new) string object with the digest
//

- (DText *) hexdigest
{
  DData *data   = [self digest     ];
  DText *string = [data tohexString];
  
  [data free];
  
  return string;
}

@end

/*===========================================================================*/

